概述

每个框架都有各自的使用领域,要根据项目的实际情况合理的选择对应的框架以及设计模式。

MVC
Model-View-Controller
这种框架模式实现了Modle层与View的分离,将一些控制交由Controller类处理,这样就可以实现一定程度上的解耦。

- Model层一般指的是数据,不管是从网络上接受到的数据还是内部产生的数据。
- View层指的就是界面
- Controller指的就是类似于管理类、

Model将数据交由Controller, Controller类再将相关的信息交给View层处理。
Android模式就是一个比较典型的MVC框架,将View层与Model层和Controller分开。Android将Activity直接看做一个Controller,但是也正是因为这个原因,也产生一定的耦合度。
因为View层可以直接控制Model层,这也就产生了一定的耦合度,一个比较好的方式是所有的方式都由一个第三方管理或者是中介类去处理,这样的话可以实现耦合性的大幅度降低。一份代码,即使View层变了,代码也不需要变。同时代码的可维护性和拓展性也大大的增加了。因为这样一来,在Activity或者是Fragment中处理的逻辑更清晰,代码也更少了。

MVP
MVP是MVC的衍生物,从推出就受到了广泛关注。Model - View - Presenter
这一种方式是将Activity视为一个View层,处理的事务交由Presenter这个中介去处理。这样就实现了View - Presenter - Model的单链。较之于MVC来说具有更大的解耦性。

分类

MVP根据实现的方式分为深引用和弱引用。这一篇博客就以简单的登陆界面介绍深引用。

##深引用的实现##

1. 创建一个接口,这个接口是包含相关的事件处理方法。Activity中需实现该接口,然后将Activity传递给Presenter。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.example.testing.mvpdemo;

public interface LoginDoInterface {

void showLoading();

void hideLoading();

void loginIn(String account, String password);

void loginSuccess();

void loginFailed();
}

2. User类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package com.example.testing.mvpdemo;

public class User {

public String getAccount() {
return account;
}

public void setAccount(String account) {
this.account = account;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

private String account;
private String password;

public User(String account, String password) {
this.account = account;
this.password = password;
}

public User() {

}
}

3. Model层

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.example.testing.mvpdemo;

public class LoginDoModle {

public static User user = null;

public User getInstance() {
if (user == null) {
user = new User();
}
return user;
}

public static void setUser(User user2) {
user = user2;
}

public static User getUser() {
return user;
}
}

4. Activity

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package com.example.testing.mvpdemo;


import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class LoginActivity extends AppCompatActivity
implements LoginDoInterface, View.OnClickListener {

private User user;
private Button button_login;
private LoginPresenter loginPresenter;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.xml_login);

init();
}

private void init() {
user = new User();
button_login = (Button) findViewById(R.id.button_login);
button_login.setOnClickListener(this);
loginPresenter = new LoginPresenter(this);
}

@Override
public void showLoading() {
Log.d("tag", "Loading......");
}

@Override
public void hideLoading() {
Log.d("tag", "Loading successful or failed");
}

@Override
public void loginIn(String account, String password) {
Log.d("tag", "Login");
}

@Override
public void loginSuccess() {
Log.d("tag", "Log success");
}

@Override
public void loginFailed() {
Log.d("tag", "Log failed");
}

@Override
public void onClick(View v) {
loginPresenter.loginStart();
}
}
  1. Presenter
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    public class LoginPresenter {

    private LoginDoInterface loginDoInterface;
    private LoginDoModle loginDoModle;

    public LoginPresenter(LoginDoInterface loginDoInterface) {
    this.loginDoInterface = loginDoInterface;
    loginDoModle = new LoginDoModle();
    }

    public void loginStart() {

    loginDoInterface.loginIn(
    loginDoModle.getInstance().getAccount(),
    loginDoModle.getInstance().getPassword());
    loginDoInterface.showLoading();
    loginDoInterface.loginSuccess();

    loginFinish();
    }

    public void loginFinish() {
    loginDoInterface.hideLoading();
    loginDoInterface.loginFailed();
    }
    }

从这里可以看出,表面上需要编写的代码增多了(实际也增多了),自己也要添加更多的类。但是,从Activity的层面上来看,整个界面变清晰了,每个功能之间的界限也很明确,最重要的一点是,不管你的界面如何变化,哪怕是推翻了重来,Activity的代码是只需要改动一个click事件的,有的时候则还有可能完全不改动,一份代码对应多份界面。
同时,如果哪天项目需要增加功能或者维护,这样的方式也更清晰,更容易处理。

另外,对于深引用的方式来说,因为是直接把Activity传递过去的,如果产生了一个网络请求,而在请求未返回的时候Activity就已经被摧毁了。这时候就会造成内存泄露,而在这种情况下就建议使用弱引用的方式,将Presenter的绑定与解绑跟Activity以及Fragment的生命周期绑定起来。弱引用将会在下篇博客中进行介绍。

建议
一般小的或者是时间要求特别紧的项目可以暂不用MVP,MVC,MVVM这些框架,因为会产生很多的接口,工作量也有一定的增加。但是对于大中型项目,为了项目的可维护性和可拓展性,建议使用。而至于使用MVP, MVC还是MVVM,就要根据项目的实际情况来选择。